home *** CD-ROM | disk | FTP | other *** search
/ Software Vault: The Gold Collection / Software Vault - The Gold Collection (American Databankers) (1993).ISO / cdr25 / me310.zip / UE310C.ZIP / AOSVS.C < prev    next >
C/C++ Source or Header  |  1989-03-18  |  56KB  |  1,936 lines

  1. /*
  2.  * aosvs.c  -  AOS/VS & MV/UX version of the termio.c module
  3.  *
  4.  * The functions in this module deal with the O/S in reading/writing
  5.  * characters from/to the screen.  We also deal with various wiedness things
  6.  * in dealing with the AOS/VS file system such as ACL's and elementsizes.
  7.  * This has been written primarily for AOS/VS but should work for MV/UX as
  8.  * well.  No promises though.
  9.  *
  10.  * AOS/VS and MV/UX are products of Data General Corporation, Westboro MA.
  11.  *
  12.  * Authors:
  13.  *          Daniel Lawrence --- doing MicroEmacs... stuff copied into here...
  14.  *          Douglas Rady ------ most of the rest of the stuff here
  15.  * Credits:
  16.  *          Michael Meissner -- beating Doug over the head with advice and info.
  17.  *                              on AOS/VS "C" compiler.     THANK YOU!!!!!!!!!!
  18.  *          Bill Benedetto
  19.  *          & friends      ---- beta victims, bug finders/fixers
  20.  *          GNU --------------- inspiration, software tools, clean readable BSD
  21.  *                              and USG code examples and interesting comments.
  22.  *
  23.  * Definition: uka = Unixly Known As
  24.  *
  25.  * Revision/Hack History
  26.  *  MicroEMACS v3.<9p,10> AOS/VS History
  27.  *  
  28.  *  3.09.16.00 - 3.09.16.09         ??-???-??           dcr
  29.  *      Before written history.  Suffice to say that .00 - .04 was just the
  30.  *      AOS/VS port from 3.8z, 3.9e, 3.9i and 3.9n with major cleaning up and
  31.  *      rewriting of the AOS/VS stuff.  Sub-revisions 3.09.16.05 - 3.09.16.09
  32.  *      being optimizations and various fixes.
  33.  *      Yawn...
  34.  *
  35.  *  3.09.16.10                      25-Aug-88           dcr
  36.  *      Changed  do_system_end()  in  aosvs.c  to check for execution of a 
  37.  *    macro as basis for not executing an  mlreply("Continue")  call.
  38.  *      Also fixed  stime()  in  aosvs.c  so it just plain worked.
  39.  *      #$&^@*&(+$#!!!!
  40.  *      Also added  REPLYNL  in  estruct.h  and made use of CR or NL in the
  41.  *      mlreply()  routine in  input.c  compile time conditional.
  42.  *
  43.  *  3.09.16.11                      13-Sep-88           dcr
  44.  *      Start of written hisory.  This is a momentous event in the course of
  45.  *      AOS/VS MicroEMACS history: doug writes some change doc.!!! Yeah!!!
  46.  *      Changed several functions to force the  $builtin  version as a trade of
  47.  *      more code size for more speed (usually defaulted to $builtin anyway...).
  48.  *
  49.  *  3.09.16.12                      14-Sep-88           dcr
  50.  *      Recompiled with revision 4.00 of AOS/VS C.  A miracle...
  51.  *
  52.  *  3.09.16.13                      12-Oct-88           dcr
  53.  *      Changed to have the temporary file for pipecmd() be created in a system
  54.  *      wide temporary file directory known as :TMP, uka /tmp.  You paranoids
  55.  *      can create :TMP as a CPD with max. size of 2048 blocks and an ACL of
  56.  *      +,WE and you should be able to relax a nibble.
  57.  *      Creates temp. file with ACL of  username,OWAR
  58.  *
  59.  *  3.09.16.14                      13-Oct-88           dcr
  60.  *      Put in MCA's hack to reduce memory consumption when VIEWing a file.
  61.  *      Modified  lalloc()  in line.c  Test case of paru.h saved 27 2Kb pages.
  62.  *
  63.  *  3.10.00.00                      09-Nov-88           dcr
  64.  *      Begin code porting for 3.10 BETA.
  65.  *
  66.  *  3.10.00.01                      20-Dec-88           dcr
  67.  *      Implemented multi-language messages in  aosvs.c  per 3.10 BETA.
  68.  *
  69.  *  3.10.00.02                      26-Dec-88           dcr
  70.  *      Tracked down some un-documented runtime optimizations and got
  71.  *      a working version. Also resolved timeset() references.
  72.  *
  73.  *  3.10.00.03                      17-Jan-89           dcr
  74.  *      Cleaned up for shipping to Dan.  Put in some missing code for input.c
  75.  *
  76.  *  3.10.00.04                      17-Jan-89           dcr
  77.  *      Put in some optimizations regarding TTflush() and ostring() in the
  78.  *      bind.c, input.c and aosvs.c files.  This freed 2Kb... but not for long.
  79.  *
  80.  *  3.10.00.05                      17-Jan-89           dcr
  81.  *      Some memory optimization in  exec.c  and  input.c for small regain.
  82.  *
  83.  *  3.10.00.06 - 3.10.00.27     02-Mar-89 - 10-Mar-89   dcr
  84.  *      Various changes. Cleaned up the AOS/VS changes in other modules so 
  85.  *      we actually work right.  Added conditionals for using either BSD or
  86.  *      USG console i/o (BSD doesn't seem to work).  Reclaimed about 4Kb of 
  87.  *      memory in various places and made some of these optimizations compile
  88.  *      time conditional. We are still using .890+ ms to start up intead of the
  89.  *      .520+ ms that we took with 3.9p. Not much hope there... but...
  90.  *      Various tweaks here and there.  Added the skip of nulls when reading in
  91.  *      a file (most unpleasant results if we don't).  Lost some memory to the
  92.  *      USG console i/o stuff.  Threw out the BSD console i/o stuff, sigh....
  93.  *
  94.  *  3.10.00.28                      10-Mar-89           dcr
  95.  *      Stuck in the  aosvs$unix_to_aosvs_path()  routine to replace the code
  96.  *      in resolve_pathname().  The new routine does a fairly complete job of
  97.  *      converting Unix(tm) pathnames to AOS/VS format. It also handles the 
  98.  *      Ms-Dog '\' path seperator.
  99.  *  
  100.  *  3.10.00.29                      16-Mar-89           dcr
  101.  *      Changed pathname expansion to be invisible to user.  Required changes
  102.  *      to  fileio.c  to #if AOSVS  replace the fopen() calls with our xxfopen()
  103.  *      call which does the pathname expansion.  Allowed removal of all the
  104.  *      related to the EXPPATH define.  Also changed several routines here.
  105.  *      Allows user to reference buffer & file names w/o "unexpanding" the 
  106.  *      orginal pathname.
  107.  *      Diff'd & sent to Dan.
  108.  *
  109.  */
  110.  
  111. #nolist
  112. #include        <stdio.h>           /* get the usual */
  113. #list
  114. #include        "estruct.h"         /* get the MicroEMACS stuff */
  115.  
  116. #ifdef  AOSVS | MV_UX               /* should this be done? */
  117.  
  118. #define dashertermdef   1           /* might not be used any more */
  119.  
  120. #nolist
  121. #include        "edef.h"            /* get the MicroEMACS extern's */
  122. #include        "elang.h"
  123. #list
  124.  
  125. /* There is no kitchen sink in C so we can't include it. Maybe in C++... */
  126. #nolist
  127. #include    <paru.h>                /* AOS/VS system mnemonics */
  128. #include    <sysid.h>               /* AOS/VS system call mnemonics */
  129. #include    <packets/characteristics.h> /* sys call packet for terminal char.*/
  130. #include    <packets/create.h>      /* sys call packet to create files */
  131. #include    <packets/filestatus.h>  /* sys call packet to get file info */
  132. #include    <packets/misc.h>        /* misc. sys call packets (?SYSPRV) */
  133.  
  134. /* And now... the Unix(tm) stuff... */
  135. #include    <fcntl.h>               /* terminal file control stuff */
  136. #include    <signal.h>              /* the signals... */
  137. #include    <termio.h>              /* more terminal control stuff */
  138. #list
  139.  
  140. /*
  141.     Variables!!!   Functions!!!  Externals!!!!
  142. */
  143. struct  termio  old_in_termio;  /* original stdin terminal characteristics */
  144. struct  termio  new_in_termio;  /* stdin characteristics to use inside */
  145.  
  146. int kbdpoll;                    /* type ahead polling flag      */
  147. int kbdflgs;                    /* saved keyboard fd flags      */
  148. int kbdqp;                      /* there is a char in kbdq      */
  149. char kbdq;                      /* char we've already read      */
  150.  
  151. /*
  152.     some D.G. supplied AOS/VS & MV/UX specific functions
  153.  
  154.     _toaos_fid() - changes UNIX(tm)  pathname to AOS/VS pathname (Thank you!)
  155.     traceback() - calls the ?SNAP LANG_RT routine for error traceback
  156. */    
  157. /*extern int  _toaos_fid(char*, char* );*/
  158. extern VOID traceback(int );
  159.  
  160. /*
  161.     This is how we make an MV/Eclipse accumulator in C with almost all options.
  162. */
  163. union accumulator {                 /* dearly beloved, we are gathered here...*/
  164.     unsigned long * ptr;            /* pointer to unsigned long (generic) */
  165.     char *          cptr;           /* pointer to char */
  166.     unsigned int  * pint;           /* pointer to unsigned int */
  167.     unsigned short *psht;           /* pointer to short */
  168.     unsigned long   ulng;           /* unsigned long */
  169.     signed long     lng;            /* signed long */
  170.     unsigned int    uin;            /* unsigned int */
  171.     signed int      in;             /* signed int */
  172.     unsigned short usht;            /* unsigned short */
  173.     unsigned char   chr;            /* a char, unsigned of course!!! */
  174. } ac0, ac1, ac2;                    /* our bountiful accumulators, sigh... */
  175.     
  176.  
  177. P_CREATE    create_pkt;             /* file create system call packet */
  178. P_FSTAT     fstat_pkt;              /* file status system call packet */
  179. char acl_buf[ $MXACL ];             /* ACL buffer, gotta protect things... */
  180. char *crt_eol="\013";               /* Dasher D2xx commands */
  181. char *crt_eop="\014";               /* Dasher D2xx commands */
  182. int dimsts, revsts;
  183. int su_mode;                        /* Superuser mode flag */
  184. #define TLINE_LEN   512
  185. char tline[TLINE_LEN];                /* command line for cli/shell/program calls */
  186.  
  187. extern VOID do_system();        /* calls the cli/shell/program */
  188. extern VOID do_system_end();    /* cleans up after cli/shell/program calls */
  189. extern VOID init_tline();       /* inits the command line for cli/shell... */
  190. extern VOID ttputs();
  191. extern VOID in_init();
  192. extern FILE *ffp;               /* file stream pointer used in fileio.c */
  193. extern int vttidy();            /* MicroEMACS routine to tidy up the screen */
  194.  
  195. extern int              aosvs$expand_pathname();
  196. extern void             aosvs$unix_to_aosvs_path();
  197. #endif
  198.  
  199. FILE *STDIN, *STDOUT;           /* Needed since the array of files went away.*/
  200.                                 /* Of course, if _iob changes, we'll have to */
  201.                 /* bend over since we use  ->_file  in _iob. */
  202.  
  203. static int mexist;    /* is the mouse driver installed? */
  204. static int nbuttons;    /* number of buttons on the mouse */
  205. static int oldbut;    /* Previous state of mouse buttons */
  206.  
  207. /*------------------------------------------------------------------------------
  208.  *  resolve_full_pathname(char*, char*) - resolves a filename or pathname to
  209.  *  full AOS/VS pathname via the ?GRNAME system call.  If the file does not
  210.  *  exsist then the current working directory is assumed by  AOS/VS.
  211.  *
  212.  *  Returns  FIOSUC  if  from_path  is found or  FIOFNF  if it isn't found.
  213.  */
  214. int resolve_full_pathname(from_path, to_path)
  215.  
  216. char *from_path, *to_path;      /* resolve "from" pathname "to" pathname */
  217. {
  218.     if (aosvs$expand_pathname(from_path, to_path))
  219.         return(FIOFNF);
  220.  
  221.     return(FIOSUC);
  222. }
  223.  
  224. /*
  225.  *  ffwopen() - AOS/VS specific version of the ffwopen() routine found in the
  226.  *  fileio.c source.  This version will attempt to recreate the edit file
  227.  *  (if it exists) with the existing edit file ACL, elementsize, filetype and
  228.  *  recordsize parameters as determined via a ?FSTAT filestatus system call.
  229.  *
  230.  *  Returns  FIOSUC  if file is opened or  FIOERR  if not opened.
  231.  */
  232. int ffwopen(bfilnam, sfilnam)
  233.  
  234. char *bfilnam;    /* buffer file name */
  235. char *sfilnam;    /* save file name or NULL */
  236. {
  237.     char bfnam[NFILEN], sfnam[NFILEN];
  238.     char *tptr;
  239.  
  240.     /* some initializations */
  241.     zero((char *) &create_pkt, sizeof(create_pkt));
  242.     zero((char *) &fstat_pkt, sizeof(fstat_pkt));
  243.     zero(acl_buf, $MXACL);
  244.  
  245.     strcpy(bfnam, bfilnam);
  246.     if (sfilnam) {
  247.         strcpy(sfnam, sfilnam);
  248.     resolve_full_pathname(sfnam, sfnam);
  249.         tptr = sfnam;
  250.     } else {
  251.         tptr = bfnam;    
  252.     }
  253.     
  254.     create_pkt.ctim = -1L;      /* take default file creation time */
  255.     create_pkt.cacp = -1L;      /* take default file creation acl */
  256.     create_pkt.cdel = -1L;      /* take default file creation elementsize */
  257.     create_pkt.cmil = -1L;      /* take default file creation max. index levels */
  258.     fstat_pkt.stim = -1L;
  259.     fstat_pkt.sacp = -1L;
  260.  
  261.     /* attempt to get full AOS/VS pathname of the file */
  262.     if  ((resolve_full_pathname(bfnam, bfnam)) == FIOFNF) { /* edit file found? */
  263.         /* bfnam not found, create one with default specs. */
  264.         create_pkt.cftyp_format = $ORDS;    /* data sensitive record type */
  265.         create_pkt.cftyp_entry  = $FTXT;    /* text file type */
  266.         ac2.ptr = &create_pkt;
  267.         ac1.lng = 0L;
  268.  
  269.         ac0.cptr = tptr;
  270.  
  271.         /* have AOS/VS attempt to create the file */
  272.         if  (sys($CREATE, &ac0, &ac1, &ac2))
  273.             goto fubar;
  274.  
  275.     } else {    /* bfnam found, get filestatus info. for recreation of bfnam */ 
  276.         ac2.ptr = &fstat_pkt;
  277.         ac1.lng = 0L;
  278.         ac0.cptr = bfnam;
  279.         /* have AOS/VS attempt to get the file information for us */
  280.         if  (sys($FSTAT, &ac0, &ac1, &ac2))
  281.             goto fubar;
  282.  
  283.         /*
  284.             Get ACL of bfnam.  If we can't get that then we get the
  285.             default ACL and use that.
  286.         */
  287.         ac0.cptr = bfnam;
  288.         ac1.cptr = acl_buf;
  289.         ac2.lng = 0L;
  290.         if  (sys($GACL, &ac0, &ac1, &ac2)) {    /* try to get the file ACL */
  291.             /* can't get ACL of file, get default ACL */
  292.             ac0.lng = 0L;
  293.             ac2.lng = 0L;
  294.             ac1.cptr = acl_buf;
  295.             sys($DACL, &ac0, &ac1, &ac2); /* try to get user default ACL */
  296.         }
  297.  
  298.         /*
  299.             Delete  sfnam  file.  We don't care about any errors on this.
  300.         */
  301.         ac0.cptr = tptr;
  302.         ac1.lng = 0L;
  303.         ac2.lng = 0L;
  304.         sys($DELETE, &ac0, &ac1, &ac2);   /* delete it */
  305.     
  306.         /*
  307.             Set up the packet for the file create system call
  308.         */
  309.         create_pkt.cftyp_format = fstat_pkt.styp_format;    /* file format  */
  310.         create_pkt.cftyp_entry  = fstat_pkt.styp_type;      /* file type    */
  311.         create_pkt.ccps = fstat_pkt.scps;   /* recordsize, if any */
  312.         create_pkt.cacp = acl_buf;          /* acl buffer ptr   */
  313.         create_pkt.cdeh = fstat_pkt.sdeh;   /* element size     */
  314.         create_pkt.cmil = fstat_pkt.smil;   /* max. index level */
  315.  
  316.         /*
  317.             Make system call to create a file with supplied specs.
  318.         */
  319.         ac2.ptr  = &create_pkt;
  320.         ac0.cptr = tptr;
  321.  
  322.         ac1.lng = 0L;
  323.         if  (sys($CREATE, &ac0, &ac1, &ac2))    /* attempt file create */
  324.             goto fubar;
  325.     }
  326.  
  327.     if  ((ffp = fopen(tptr, "a")) == NULL)
  328.             goto fubar;
  329.  
  330. #if     ISADIR
  331.     if  (isadirectory(ffp)) {   /* check to see if file is a directory */
  332.         mlwrite(TEXT216);       /* bitch... */
  333.     ffclose(ffp);           /* yes, close it and get out!!! */
  334.         return(FIOERR);         /* actual checking code in O/S modules */
  335.     }
  336. #endif
  337.  
  338.     return(FIOSUC);
  339.  
  340.     /*
  341.         Common error exit for all  ffwopen()  errors
  342.     */
  343. fubar:
  344.     mlwrite(TEXT155);
  345. /*    mlwrite("Cannot open file for writing");*/
  346.     return(FIOERR);
  347. }
  348.  
  349. /*
  350.  *  unlink() - delete a file - called from  writeout()  in  file.c
  351.  *
  352.  *  This routine replaces the DG supplied  unlink()  since we don't use the
  353.  *  link() unlink() combination to rename files.  Saves some memory.
  354.  *
  355.  */
  356. int unlink(del_fnam)
  357.  
  358. char *del_fnam;        /* name of file to delete */
  359. {
  360.     char dtmp[NFILEN];
  361.  
  362.     strcpy(dtmp, del_fnam);
  363.     resolve_full_pathname(dtmp, dtmp);
  364.     ac0.cptr = dtmp;
  365.     ac1.lng = 0L;
  366.     ac2.lng = 0L;
  367.     if (sys($DELETE, &ac0, &ac1, &ac2))    /* attempt to delete it */
  368.         return(-1);                           /* normal error return */
  369.     return(0);                                /* normal okay return */
  370. }
  371.  
  372. /*
  373.  *  rename() - rename a file - called from  writeout()  in  file.c
  374.  */
  375. int rename(from_nam, to_nam)
  376.  
  377. char *from_nam;     /* rename from name */
  378. char *to_nam;       /* rename to name */
  379. {
  380.     char ftmp[NFILEN], ttmp[NFILEN];
  381.  
  382.     /*
  383.         First we convert Unix(tm) or Ms-dog paths to Aos/Vs paths.
  384.         Second we strip the actual filename from the "to" path by going to the
  385.     end of the string and working our way backward until we find a pathname
  386.     seperator which under AOS/VS is a colon (:).
  387.     */
  388.     strcpy(ftmp, from_nam);
  389.     strcpy(ttmp, to_nam);
  390.     resolve_full_pathname(ftmp, ftmp);
  391.     resolve_full_pathname(ttmp, ttmp);
  392.  
  393.     ac1.cptr = ttmp + (sizeof(char) * strlen(ttmp));
  394.     while ((ac1.cptr >= ttmp) && (*ac1.cptr != ':') && (*ac1.cptr != '='))
  395.         --ac1.cptr;
  396.  
  397.     ++ac1.cptr;     /* move pointer from seperator to 1st char in filename */
  398.     ac0.cptr = ftmp;
  399.     ac2.lng = 0L;
  400.     if  (sys($RENAME, &ac0, &ac1, &ac2))    /* attempt the rename */
  401.         return(-1);   /* oops!!! */
  402.     return(0);        /* okay... */
  403. }
  404.  
  405. /*
  406.  * This function gets called just before we go back home to the command
  407.  * interpreter.
  408.  */
  409. VOID ttclose()
  410. {
  411.     fflush(stdout);
  412.     fflush(stdin);
  413.     ioctl(STDIN->_file, TCSETA, &old_in_termio);     /* restore terminal settings */
  414.     fcntl(STDIN->_file, F_SETFL, kbdflgs);
  415. }
  416.  
  417. /*
  418.  * Write a character to the display.
  419.  */
  420. #if TTPUTC == 0
  421. VOID ttputc(c)
  422. {
  423.     putc(c, stdout);
  424. }
  425. #endif
  426.  
  427. /*
  428.  * Flush terminal buffer. Does real work where the terminal output is buffered
  429.  * up. A no-operation on systems where byte at a time terminal I/O is done.
  430.  */
  431. #if TTFLUSH == 0
  432. VOID ttflush()
  433. {
  434.     fflush(stdout);
  435. }
  436. #endif
  437.  
  438. unsigned int extcode(c)
  439.  
  440. unsigned int c;
  441.  
  442. {
  443.     if ((c == 1 || c == 8 || c == 17 || c == 23) || (c >= 24 && c <=26)
  444.         || (c >= 32 && c <= 110) || (c >= 112 && c <= 126))   /* 111 is mouse */
  445.         return((c & 255) | SPEC);
  446.  
  447.     return(c & 255);
  448. }
  449.  
  450. /*    input buffers and pointers    */
  451.  
  452. #define    IBUFSIZE    64    /* this must be a power of 2 */
  453.  
  454. unsigned char in_buf[IBUFSIZE];    /* input character buffer */
  455. int in_next = 0;        /* pos to retrieve next input character */
  456. int in_last = 0;        /* pos to place most recent input character */
  457.  
  458. VOID in_init()  /* initialize the input buffer */
  459.  
  460. {
  461.     in_next = in_last = 0;
  462. }
  463.  
  464. int in_check()    /* is the input buffer non-empty? */
  465.  
  466. {
  467.     if (in_next == in_last)
  468.         return(FALSE);
  469.     else
  470.         return(TRUE);
  471. }
  472.  
  473. VOID in_put(event)
  474.  
  475. int event;    /* event to enter into the input buffer */
  476.  
  477. {
  478.     in_buf[in_last++] = event;
  479.     in_last &= (IBUFSIZE - 1);
  480. }
  481.  
  482. int in_get()    /* get an event from the input buffer */
  483.  
  484. {
  485.     register int event;    /* event to return */
  486.  
  487.     event = in_buf[in_next++];
  488.     in_next &= (IBUFSIZE - 1);
  489.     return(event);
  490. }
  491. #if    MOUSE
  492. int checkmouse()
  493.  
  494. {
  495.     register int k;        /* current bit/button of mouse */
  496.     register int event;    /* encoded mouse event */
  497.     int newbut;        /* new state of the mouse buttons */
  498.     int mousecol;        /* current mouse column */
  499.     int mouserow;        /* current mouse row */
  500.     int sstate;        /* current shift key status */
  501.  
  502.     /* check to see if any mouse buttons are different */
  503. /*    rg.x.ax = 3;*/    /* Get button status and mouse position */
  504. /*    int86(0x33, &rg, &rg);*/
  505. /*    newbut   = rg.x.bx;*/
  506. /*    mousecol = rg.x.cx >> 3;*/
  507.     mouserow = rg.x.dx >> 3;
  508.  
  509.     /* get the shift key status as well */
  510.     sstate = 0;
  511. /*    rg.h.ah = 2;*/    /* return current shift status */
  512. /*    int86(0x16, &rg, &rg);*/
  513. /*    sstate = rg.h.al;*/
  514.  
  515.     for (k=1; k != (1 << nbuttons); k = k<<1) {
  516.         /* For each button on the mouse */
  517.         if ((oldbut&k) != (newbut&k)) {
  518.             /* This button changed, generate an event */
  519.             in_put(0);
  520.             in_put(MOUS >> 8);
  521.             in_put(mousecol);
  522.             in_put(mouserow);
  523.             event = ((newbut&k) ? 0 : 1);    /* up or down? */
  524.             if (k == 2)            /* center button? */
  525.                 event += 4;
  526.             if (k == 4)            /* right button? */
  527.                 event += 2;
  528.             if (sstate & 3)            /* shifted */
  529.                 event += 'A';
  530.             else if (sstate & 4)        /* controled? */
  531.                 event += 1;
  532.             else
  533.                 event += 'a';        /* plain */
  534.             in_put(event);
  535.             oldbut = newbut;
  536.             return(TRUE);
  537.         }
  538.     }
  539.     return(FALSE);
  540. }
  541. #endif
  542.  
  543. int doschar()
  544.  
  545. {
  546. /* USG - SysV console i/o - From  "C Users Journal", April 1989, Vol. 7, # 9 */
  547.     if(kbdqp)               /* any typeahead known? */
  548.         kbdqp = FALSE;      /* yes, clear flag & return typeahead char */
  549.     else {                  /* no typeahead. */
  550.         if (fcntl(STDIN->_file, F_SETFL, kbdflgs) < 0 && kbdpoll)
  551.             return(FALSE);
  552.         kbdpoll = FALSE;
  553.         read(STDIN->_file, &kbdq, 1);   /* wait and get a char */
  554.     }
  555.     if (kbdq == '\036') {   /* D.G. Dasher CRT function key lead-in? */
  556.         in_put(SPEC >> 8);  /* ??? stash in the keyboard buffer stuff ??? */
  557.         return(0);
  558.     }
  559.     return (kbdq & 255);
  560. }
  561.  
  562. /*
  563.  * Read a character from the terminal, performing no editing and doing no echo
  564.  * at all.
  565.  */
  566. int ttgetc()
  567. {
  568.         /* return any keystrokes waiting in the
  569.         type ahead buffer */
  570. ttc:    if (in_check())
  571.         return(in_get());
  572.  
  573.     if (typahead())
  574.         return(doschar());
  575.  
  576.     /* with no mouse, this is a simple get char routine */
  577.     if (mexist == FALSE || mouseflag == FALSE)
  578.             return(doschar());
  579.  
  580. #if    MOUSE
  581.     /* turn the mouse cursor on */
  582. /*    rg.x.ax = 1;*/    /* Show Cursor */
  583. /*    int86(0x33, &rg, &rg);*/
  584.     /* loop waiting for something to happen */
  585.     while (TRUE) {
  586.         if (typahead())
  587.             break;
  588.         if (checkmouse())
  589.             break;
  590.     }
  591.  
  592.     /* turn the mouse cursor back off */
  593. /*    rg.x.ax = 2;*/    /* Hide Cursor */
  594. /*    int86(0x33, &rg, &rg);*/
  595.  
  596.         goto ttc:
  597. #endif  /* MOUSE */
  598. }
  599.  
  600. #if     TYPEAH
  601. /* typahead:    Check to see if any characters are already in the
  602.                 keyboard buffer.  Hurray for kludges!!!
  603. */
  604. int typahead()
  605. {
  606. /* USG - SysV console i/o - From  "C Users Journal", April 1989, Vol. 7, # 9 */
  607.     if (!kbdqp) {
  608.         if (fcntl(STDIN->_file, F_SETFL, (kbdflgs | O_NDELAY)) < 0 && kbdpoll)
  609.             return(FALSE);
  610.         kbdpoll = TRUE;
  611.         kbdqp = (1 == read(STDIN->_file, &kbdq, 1));
  612.     }
  613.     return(kbdqp);
  614. }
  615.  
  616. #endif  /* TYPEAH */
  617.  
  618. /*      Spawn:  various DOS access commands
  619.                 for MicroEMACS ver 3.9e
  620. */
  621.  
  622.  
  623. /*
  624.  * Create a subjob with a copy of the command intrepreter in it. When the
  625.  * command interpreter exits, mark the screen as garbage so that you do a full
  626.  * repaint. Bound to "^X C".
  627.  */
  628. int spawncli(f, n)
  629. {
  630.     register char *cp;
  631.  
  632.     /* don't allow this command if restricted */
  633.     if (restflag)
  634.         return(resterr());
  635.  
  636. #if     MV_UX
  637.     TTflush();
  638.     TTclose();                              /* stty to old settings */
  639.     if ((cp = getenv("SHELL")) != NULL && *cp != '\0')
  640.         system(cp);
  641.     else
  642.         system("exec /bin/sh");
  643. #endif
  644.  
  645. #if     AOSVS
  646.     init_tline();
  647.     strcat(tline,"CHAIN/1=AB/2=AB,:CLI,EMACS_SET_CLI_PREFIX");
  648.     do_system();
  649. #endif
  650.  
  651.     sleep(2);
  652.     return(TRUE);
  653. }
  654.  
  655. /*
  656.  * Run a one-liner in a subjob. When the command returns, wait for a single
  657.  * character to be typed, then mark the screen as garbage so a full repaint is
  658.  * done. Bound to "C-X !".
  659.  */
  660. int spawn(f, n)
  661. {
  662.     register int    s;
  663.     char            line[NLINE];
  664.  
  665.     /* don't allow this command if restricted */
  666.     if (restflag)
  667.         return(resterr());
  668.  
  669.     if ((s=mlreply("!", line, NLINE)) != TRUE)
  670.         return (s);
  671.     init_tline();
  672.     strcat(tline,line);
  673.     do_system();
  674.     do_system_end();
  675.     return (TRUE);
  676. }
  677.  
  678. /*
  679.  * Run an external program with arguments. When it returns, wait for a single
  680.  * character to be typed, then mark the screen as garbage so a full repaint is
  681.  * done. Bound to "C-X $".
  682.  */
  683.  
  684. int execprg(f, n)
  685.  
  686. {
  687.     register int    s;
  688.     char            line[NLINE];
  689.  
  690.     /* don't allow this command if restricted */
  691.     if (restflag)
  692.         return(resterr());
  693.  
  694.     if ((s=mlreply("!", line, NLINE)) != TRUE)
  695.         return (s);
  696.     strcpy(tline, line);
  697.     do_system();
  698.     do_system_end();
  699.     return (TRUE);
  700. }
  701.  
  702. /*
  703.  * Pipe a one line command into a window
  704.  * Bound to ^X @
  705.  *
  706.  * This command REQUIRES a directory named :TMP or a link by that name to 
  707.  * another directory such as :SL_TEMPS.  This diectory should have an
  708.  * ACL of  +,RWE  which will allow all users to access it.  This diectory is
  709.  * where the output file for this command is placed.  This was done because
  710.  * the sons of MircoEMACS do not always have the same privileges.  The file
  711.  * is of the pathname :TMP:pid.MICRO_EMACS_COMMAND where "pid" is the PID
  712.  * of the MicroEMACS process.  Also note that this sort of follows the UNIX(tm)
  713.  * convention for a common temporary file directory.
  714.  * The temp. file is created with an ACL of  username,OWAR
  715.  *
  716.  * See the THINGS_TO_DO.TXT for planned enhancements in this area.
  717.  *
  718.  */
  719. int pipecmd(f, n)
  720. {
  721.     register int    s;      /* return status from CLI */
  722.     register WINDOW *wp;    /* pointer to new window */
  723.     register BUFFER *bp;    /* pointer to buffer to zot */
  724.     char    line[NLINE];    /* command line send to shell */
  725.     const char pipecmd_bname[] = "command";
  726.     char pipecmd_filnam[NFILEN] = ":tmp:";  /* must be AOS/VS format!!!! */
  727.  
  728.  
  729.     /* don't allow this command if restricted */
  730.     if (restflag)
  731.         return(resterr());
  732.  
  733.     /* get the users pid and build a pathname for our scratch file */
  734.     ac0.ulng = 0L;
  735.     ac2.ulng = 0L;
  736.     ac1.ulng = -1L;
  737.     sys($PNAME, &ac0, &ac1, &ac2);    /* get our PID */
  738.     itoa(ac1.in, line);
  739.     strcat(pipecmd_filnam, line);     /* build temp. filename */
  740.     strcat(pipecmd_filnam, ".micro_emacs_command");
  741.  
  742.     zero((char *) &create_pkt, sizeof(create_pkt));
  743.     zero(acl_buf, $MXACL);
  744.     ac2.cptr = &acl_buf;
  745.     ac0.ulng = -1L;
  746.     ac1.ulng = -1L;
  747.     sys($GUNM, &ac0, &ac1, &ac2);     /* get our user name */
  748.     ac0.cptr = &acl_buf[strlen(acl_buf)];
  749.     ac0.cptr++;
  750.     *ac0.cptr = ($FACO | $FACW | $FACA | $FACR);  /* specify the ACL */
  751.     ac0.cptr++;
  752.     *ac0.cptr = '\000';
  753.     create_pkt.cacp = &acl_buf;         /* load addr of temp file ACL */
  754.  
  755.     create_pkt.ctim = -1L;
  756.     create_pkt.cdel = -1L;
  757.     create_pkt.cmil = -1L;
  758.     create_pkt.cftyp_format = $ORDS;    /* data sensitive */
  759.     create_pkt.cftyp_entry  = $FTXT;    /* TEXT file type */
  760.     ac2.ptr = &create_pkt;
  761.     ac1.lng = 0L;
  762.     ac0.cptr = &pipecmd_filnam;
  763.     sys($CREATE, &ac0, &ac1, &ac2);   /* have AOS/VS create the temp file */
  764.  
  765.     /* get the command to pipe in */
  766.     if ((s=mlreply("@", line, NLINE)) != TRUE)
  767.         return(s);
  768.  
  769.     /* get rid of the command output buffer if it exists */
  770.     if ((bp=bfind(pipecmd_bname, FALSE, 0)) != FALSE) {
  771.         /* try to make sure we are off screen */
  772.         wp = wheadp;
  773.         while (wp) {
  774.             if (wp->w_bufp == bp) {
  775.                 onlywind(FALSE, 1);
  776.                 break;
  777.             }
  778.             wp = wp->w_wndp;
  779.         }
  780.         if (zotbuf(bp) != TRUE)
  781.             return(FALSE);
  782.     }
  783.  
  784.     s = 0;                          /* init. index into line        */
  785.     init_tline();
  786.     strcat(tline,"LISTFILE,");      /* give CLI an @LIST to use     */
  787.     strcat(tline,pipecmd_filnam);           /* tack on the filename for @LIST */
  788.     strcat(tline,";");              /* separate the commands        */
  789.     s = strpbrk(line,",; \t");      /* check for cmd line delimiters */
  790.     if (s) {                        /* find any?    */
  791.         strncat(tline,line,(s-(int) &line));/* get whats before the delimeter*/
  792.         strcat(tline,"/L");         /* tack on "use @LIST file" switch */
  793.         strcat(tline,s);            /* get the rest of the cmd line */
  794.     } else {                        /* no delimiers...      */
  795.          strcat(tline,line);        /* get the cmd line     */
  796.         strcat(tline,"/L");         /* tack on "use @LIST file" switch*/
  797.     }
  798.     strcat(tline,";BYE/L=@NULL");   /* tell CLI to die quietly      */
  799.     do_system();
  800.     s = TRUE;
  801.  
  802.     /* split the current window to make room for the command output */
  803.     if (splitwind(FALSE, 1) == FALSE)
  804.         goto fubar;
  805.  
  806.     /* and read the stuff in */
  807.     if (getfile(pipecmd_filnam, FALSE) == FALSE)
  808.         goto fubar;
  809.  
  810.     /* make this window in VIEW mode, update all mode lines */
  811.     curwp->w_bufp->b_mode |= MDVIEW;
  812.     wp = wheadp;
  813.     while (wp) {
  814.         wp->w_flag |= WFMODE;
  815.         wp = wp->w_wndp;
  816.     }
  817.  
  818.     /* and get rid of the temporary file */
  819.     unlink(pipecmd_filnam);
  820.     return(TRUE);
  821.  
  822. fubar:
  823.     unlink(pipecmd_filnam);
  824.     return(FALSE);
  825. }
  826.  
  827. /*
  828.  * filter a buffer through an external DOS program
  829.  * Bound to ^X #
  830.  */
  831. int filter(f, n)
  832.  
  833. {
  834.     mlwrite(TEXT217);
  835. /*    mlwrite("[Not available yet under AOS/VS]");*/
  836.     sleep(1);
  837.     return(FALSE);
  838. }
  839.  
  840.  
  841. /*
  842.     return a system dependant string with the current time
  843.     original version didn't work.  modified idea of bill benedetto by
  844.     doug rady.  note the use of sys($ITIME, ...)  instead of sys_itime() 
  845. */
  846. char *PASCAL NEAR timeset()
  847.  
  848. {
  849.     register char *sp;      /* temp string pointer */
  850.     short int tvec[2];
  851.     extern char *dg_ctime();
  852.  
  853.     ac0.ulng = 0L;
  854.     ac1.ulng = 0L;
  855.     ac2.ulng = 0L;
  856.     sys($ITIME, &ac0, &ac1, &ac2);    /* get system time */
  857.     tvec[0] = ac2.in;
  858.     ac1.lng /= 32768L;
  859.     tvec[1] = (int)(ac1.lng/2L);
  860.     sp = dg_ctime(tvec);
  861.     sp[ strlen(sp)-1 ] = NULL;
  862.     return(sp);
  863. }
  864.  
  865. VOID init_tline()
  866. {
  867.     extern char *curdir();
  868.  
  869.     tline[0] = '\000';
  870.     strcat(tline, "DIR,");
  871.     curdir(&tline[4]);
  872.     strcat(tline, ";");
  873.     return;
  874. }
  875.  
  876. VOID do_system()
  877. {
  878.     movecursor(term.t_nrow, 0);             /* Seek to last line.   */
  879.     mlerase();
  880.     TTclose();                              /* stty to old modes    */
  881.     system(tline);
  882.     TTkopen();
  883.     sgarbf = TRUE;
  884. }
  885.  
  886. VOID do_system_end()
  887. {
  888.     int s;
  889.  
  890.     if  (clexec == TRUE) {
  891.         mlputs(TEXT188);
  892. /*        mlputs("[End]");*/
  893.         TTflush();
  894.         while ((s = tgetc()) != '\r' && s != ' ')
  895.             ;
  896.     }
  897.     return;
  898. }
  899.  
  900. /*
  901.     Data General AOS/VS terminal handling routines
  902.   
  903.     Known types are:
  904.       DASHER D2xx/4xx series - support primarily for D2xx series
  905.       written by Doug Rady (based on ANSI.C and VMSVT.C)
  906.  */
  907. extern  VOID    ttopen();
  908. extern  VOID    ttkopen();
  909. extern  VOID    ttkclose();
  910. extern  VOID    tteeol();
  911. extern  VOID    tteeop();
  912. extern  VOID    ttbeep();
  913. extern  VOID    dashermove();
  914. extern  VOID    ansimove();
  915. extern  VOID    dasherrev();
  916. extern  VOID    ansirev();
  917. extern  int     ttcres();
  918. #if     COLOR
  919. extern  VOID    ttfcol();
  920. extern  VOID    ttbcol();
  921. #endif
  922. extern  VOID    dasherdim();
  923. extern  VOID    ansidim();
  924. extern  VOID    spal();
  925.  
  926. #define NROWS   24              /* normal # of screen rows */
  927. #define MXROWS  24              /* max # of screen rows */
  928. #define NCOLS   80              /* normal mode # of screen columns*/
  929. #define MXCOLS  135             /* wide mode # of screen columns*/
  930. #define MARGIN  4               /* size of minimim margin and   */
  931. #define SCRSIZ  64              /* scroll size for extended lines */
  932. #define NPAUSE  100             /* # times thru update to pause */
  933. #define ESC     0x16
  934. #define BEL     7
  935.  
  936. /*
  937.  * Dispatch table. All the
  938.  * hard fields just point into the
  939.  * terminal I/O code.
  940.  */
  941. noshare TERM    term    = {
  942.         MXROWS -1,
  943.         NROWS -1,
  944.         MXCOLS,
  945.         NCOLS,
  946.         MARGIN,
  947.         SCRSIZ,
  948.         NPAUSE,
  949.         &ttopen,
  950.         &ttclose,
  951.         &ttkopen,
  952.         &ttkclose,
  953.         &ttgetc,
  954. #if TTPUTC == 0
  955.         &ttputc,
  956. #endif
  957. #if TTFLUSH == 0
  958.         &ttflush,
  959. #endif
  960.         &dashermove,
  961.         &tteeol,
  962.         &tteeop,
  963.         &ttbeep,
  964.         &dasherrev,
  965.         &ttcres,
  966.         &dasherdim,
  967. #if     COLOR
  968.         &ttfcol,
  969.         &ttbcol
  970. #endif
  971. };
  972.  
  973. /*
  974.     dashermove - Move the cursor for DG Dasher
  975.  */
  976. VOID dashermove(row, col)
  977. {
  978.     TTputc('\020');
  979.     TTputc(col);
  980.     TTputc(row);
  981. }
  982.  
  983. /*
  984.     ansimove - Move the cursor for ANSI crt
  985.  */
  986. VOID ansimove(row, col)
  987.  
  988. int row, col;
  989. {
  990.     char rc_tmp[ 8 ];
  991.  
  992.     ++row;
  993.     ++col;
  994.     ttputs("\033[");
  995.     itoa(row, rc_tmp);
  996.     ttputs(rc_tmp);
  997.     TTputc(';');
  998.     itoa(col, rc_tmp);
  999.     ttputs(rc_tmp);
  1000.     TTputc('H');
  1001. }
  1002.  
  1003. /*
  1004.  *  dasherrev - set the reverse video status for DG Dasher
  1005.  */
  1006. VOID dasherrev(status)
  1007.  
  1008. int status;     /* TRUE = reverse video, FALSE = normal video */
  1009. {
  1010.     if (status)
  1011.         ttputs("\036\104");
  1012.     else
  1013.         ttputs("\036\105");
  1014. }
  1015.  
  1016. /*
  1017.  *  ansirev- set the reverse video status for ANSI crt
  1018.  */
  1019. VOID ansirev(status)
  1020.  
  1021. int status;
  1022. {
  1023.     if  (dimsts) {
  1024.         if (status) {
  1025.             ttputs("\033[0;2;7m");
  1026.         } else {
  1027.             ttputs("\033[0;2m");
  1028.         }
  1029.     } else {
  1030.         if (status) {
  1031.             ttputs("\033[0;7m");
  1032.         } else {
  1033.             ttputs("\033[0m");
  1034.         }
  1035.     }
  1036.     if  (status)
  1037.         revsts = TRUE;
  1038.     else
  1039.         revsts = FALSE;
  1040. }
  1041.  
  1042. /*
  1043.  *  dasherdim - set the dim/bright video status for DG Dasher
  1044.  */
  1045. VOID dasherdim(status)
  1046.  
  1047. int status;     /* TRUE = dim video, FALSE = bright video */
  1048. {
  1049.     if (status)
  1050.        TTputc('\034');
  1051.     else
  1052.        TTputc('\035');
  1053. }
  1054.  
  1055. /*
  1056.  *  ansidim - set the dim/bright video status for ANSI crt
  1057.  */
  1058. VOID ansidim(status)
  1059.  
  1060. int status;
  1061. {
  1062.     if  (revsts) {
  1063.         if (status) {
  1064.             ttputs("\033[0;2;7m");
  1065.         } else {
  1066.             ttputs("\033[0;7m");
  1067.         }
  1068.     } else {
  1069.         if (status) {
  1070.             ttputs("\033[0;2m");
  1071.         }
  1072.         else
  1073.         {
  1074.             ttputs("\033[0m");
  1075.         }
  1076.     }
  1077.     if  (status)
  1078.         dimsts = TRUE;
  1079.     else
  1080.         dimsts = FALSE;
  1081. }
  1082.  
  1083. /*
  1084.     ttcres - Change screen resolution (what resolution?)
  1085. */
  1086. int ttcres()
  1087. {
  1088.         return(TRUE);
  1089. }
  1090.  
  1091. VOID spal()          /* change palette string */
  1092.  
  1093. {
  1094.         /*      Does nothing here       */
  1095. }
  1096.  
  1097. #if     COLOR
  1098. /*
  1099.     ttfcol - Set the forground color (not implimented)
  1100.  */
  1101. VOID ttfcol()
  1102. {
  1103. }
  1104.  
  1105. /*
  1106.     ttbcol - Set the background color (not implimented)
  1107.  */
  1108.  
  1109. VOID ttbcol()
  1110. {
  1111. }
  1112. #endif  /* COLOR */
  1113.  
  1114. /*
  1115.     tteeol - Erase to end of line
  1116.  */
  1117. VOID tteeol()
  1118. {
  1119.     ttputs(crt_eol);
  1120. }
  1121.  
  1122.  
  1123. /*
  1124.     tteeop - Erase to end of page (clear screen)
  1125.  */
  1126. VOID tteeop()
  1127. {
  1128.     ttputs(crt_eop);
  1129. }
  1130.  
  1131.  
  1132. /*
  1133.     ttbeep - Ring the bell
  1134.  */
  1135. VOID ttbeep()
  1136. {
  1137.     TTputc('\007');
  1138. }
  1139.  
  1140. VOID ttputs(str)
  1141. char *str;
  1142. {
  1143.     while(*str) {
  1144.         putc(*str, stdout);
  1145.     str++;
  1146.     }
  1147. }
  1148.  
  1149. /*
  1150.     ttopen() - open the terminal and change characteristics for our use
  1151.  */
  1152.  
  1153. VOID ttopen()
  1154. {
  1155.     int sys_err;
  1156.     P_CHAR_EX   crt_info;               /* for ?GECHR system call */
  1157.     /*
  1158.     set some traps
  1159.     */
  1160.     signal(SIGTRAP, &traceback);
  1161.     signal(SIGIOT,  &traceback);
  1162.     signal(SIGILL,  &traceback);
  1163.     signal(SIGSEGV, &traceback);
  1164.     signal(SIGTERM, &traceback);
  1165. /*    signal(SIGINT,  &traceback);*/
  1166.     signal(SIGQUIT, &traceback);
  1167.     signal(SIGEMT,  &traceback);
  1168.     signal(SIGFPE,  &traceback);
  1169.     signal(SIGKILL, &traceback);
  1170.     signal(SIGBUS,  &traceback);
  1171.     signal(SIGSYS,  &traceback);
  1172.     signal(SIGTERM, &traceback);
  1173.  
  1174.     ac0.in = fchannel(stdout);    /* make sure it is opened */
  1175.     ac0.in = fchannel(stdin);     /* make sure it is opened */
  1176.     ac1.ulng = (BIT0 | (sizeof(crt_info)/2)); /* get characteristics flag */
  1177.     ac2.ptr = (unsigned long*) &crt_info;
  1178.  
  1179.     sys_err = sys($GECHR, &ac0, &ac1, &ac2);    /* ?GECHR system call */
  1180.  
  1181.     /*
  1182.         copy the actual stdio pointer macro values into pointers
  1183.     */
  1184.     STDIN   = stdin;
  1185.     STDOUT  = stdout;
  1186.  
  1187.     /*
  1188.         set LPP & CPL in case they aren't == defaults - idea from bill benedetto
  1189.         resetting the max. row value is condtional because some of us can
  1190.         display more than LPP lines on a screen.
  1191.     */
  1192.     term.t_ncol = (short)crt_info.char_cpl;     /* get CPL */
  1193.     term.t_nrow = ((short)crt_info.char_lpp -1);/* get LPP */
  1194.     if  (term.t_nrow > term.t_mrow)   /* only reset max. row if LPP is > */
  1195.         term.t_mrow = term.t_nrow;      /* default max. row */
  1196.  
  1197. #if XXCRT
  1198.     if  (termcode == 0) { /* CRT type given on command line? */
  1199.         /* nope, we must figure it out */
  1200.     }
  1201.     
  1202.     switch  (termcode) {
  1203.         case 0: /* Generic ANSI compliant */
  1204.             crt_eol     = "\033[K";
  1205.             crt_eop     = "\033[J";
  1206.             term.t_move = &ansimove;
  1207.             term.t_rev  = &ansirev;
  1208.             term.t_dim  = &ansidim;
  1209. /*
  1210.             term.t_getkey = &ansigetkey;
  1211. */
  1212.             break;
  1213.         case 1: /* DEC VT100 */
  1214.         case 2: /* DEC VT100K */
  1215.             crt_eol     = "\033[K";
  1216.             crt_eop     = "\033[J";
  1217.             term.t_move = &ansimove;
  1218.             term.t_rev  = &ansirev;
  1219.             term.t_dim  = &ansidim;
  1220. /*
  1221.             term.t_getkey = &vt100getkey;
  1222. */
  1223.             break;
  1224.         case 4: /* DEC VT102 */
  1225.         case 5: /* DEC VT102K */
  1226.             crt_eol     = "\033[K";
  1227.             crt_eop     = "\033[J";
  1228.             term.t_move = &ansimove;
  1229.             term.t_rev  = &ansirev;
  1230.             term.t_dim  = &ansidim;
  1231.             crt_func = (INS_CHAR | INS_LINE | DEL_CHAR | DEL_LINE);
  1232. /*
  1233.             term.t_getkey = &vt100getkey;
  1234. */
  1235.             break;
  1236.         case 7: /* DEC VT220 */
  1237.         case 8: /* DEC VT220K */
  1238.             crt_eol     = "\033[K";
  1239.             crt_eop     = "\033[J";
  1240.             term.t_move = &ansimove;
  1241.             term.t_rev  = &ansirev;
  1242.             term.t_dim  = &ansidim;
  1243. /*
  1244.             term.t_getkey = &vt220getkey;
  1245. */
  1246.             break;
  1247.         case 6: /* D.G. Dasher D4xx */
  1248.             crt_func = (INS_CHAR | INS_LINE | DEL_CHAR | DEL_LINE);
  1249.             break;
  1250.         case 3: /* D.G. Dasher D2xx */
  1251.         default;
  1252.     }
  1253. #else
  1254.     if  ((crt_info.char_cdt != char_d2xx)    /* is not CRT3 or D2xx ?  and */
  1255.     &&  (crt_info.char_cdt != char_d4xx)) {  /* is not CRT6 or D4xx or D5xx ? */
  1256.         crt_eol     = "\033[K";
  1257.         crt_eop     = "\033[J";
  1258.         term.t_move = &ansimove;
  1259.         term.t_rev  = &ansirev;
  1260.         term.t_dim  = &ansidim;
  1261.     }
  1262. #endif  /* XXCRT */
  1263.  
  1264.     /*
  1265.         change terminal charactersitcs to Unix(tm) raw mode
  1266.     */
  1267.     ioctl(STDIN->_file, TCGETA, &old_in_termio);    /* save old settings */
  1268.     new_in_termio.c_iflag = 0;            /* setup new settings */
  1269.     new_in_termio.c_oflag = 0;
  1270.     new_in_termio.c_lflag = 0;
  1271.     new_in_termio.c_cc[VTIME] = 0;
  1272.     new_in_termio.c_cc[VMIN] = 1;
  1273.     new_in_termio.c_line = BELL_LD;       /* emulate unix(tm) line handling */
  1274.     new_in_termio.c_cflag = old_in_termio.c_cflag;
  1275.     ioctl(STDIN->_file, TCSETA, &new_in_termio);
  1276.     kbdflgs = fcntl(STDIN->_file, F_GETFL, 0);
  1277.     dimsts = 0;
  1278.     revsts = 0;
  1279.  
  1280.     /*
  1281.     check for mouse here
  1282.     */
  1283.     mexist = 0;
  1284.     nbuttons = 0;
  1285.     oldbut = 0;
  1286.  
  1287.     /*
  1288.         on all screens we are not sure of the initial position
  1289.         of the cursor
  1290.     */
  1291.     ttrow = 999;
  1292.     ttcol = 999;
  1293.  
  1294.     /* assume terminal has following */
  1295.     eolexist = TRUE;
  1296.     revexist = TRUE;
  1297.     strcpy(sres, "NORMAL");
  1298.  
  1299.     /*
  1300.         here we lower the priority of this task so that the console
  1301.     reader task will always get control when we get a char.
  1302.     */
  1303.     ac0.ulng = 0L;                      /* will get TID of this task */
  1304.     ac1.ulng = 0L;                      /* will get task pri. this task */
  1305.     ac2.ulng = 0L;                      /* who knows... */
  1306.     sys($MYTID, &ac0, &ac1, &ac2);
  1307.     ac1.ulng = 100L;                    /* new task priority */
  1308.     ac2.ulng = 0L;                      /* must be zero... */
  1309.     sys($IDPRI, &ac1, &ac0, &ac2);      /* do it!!! */
  1310.  
  1311. }
  1312.  
  1313. /*
  1314.     open the keyboard
  1315. */  
  1316. VOID ttkopen()
  1317. {
  1318.     /*
  1319.         activate the MircoEmacs console characteristics
  1320.     */
  1321.     ioctl(STDIN->_file, TCSETA, &new_in_termio);
  1322.     fcntl(STDIN->_file, F_SETFL, kbdflgs);
  1323.     kbdqp = 0;
  1324.     kbdpoll = FALSE;
  1325.     kbdq = '\000';
  1326.     in_init();
  1327. }
  1328.  
  1329. VOID ttkclose()
  1330. {
  1331. }
  1332.  
  1333. #if     FLABEL
  1334. fnclabel(f, n)          /* label a function key */
  1335.  
  1336. int f,n;        /* default flag, numeric argument [unused] */
  1337.  
  1338. {
  1339.         /* on machines with no function keys...don't bother */
  1340.         return(TRUE);
  1341. }
  1342. #endif
  1343.  
  1344. /*
  1345.      Change the current working directory
  1346. */
  1347. PASCAL NEAR int chdirectory()
  1348.  
  1349. {
  1350. #if CHDIR                               /* include this code?   */
  1351.  
  1352.     /* don't allow this command if restricted    */
  1353.     if (restflag)
  1354.         return(resterr());
  1355.  
  1356.     if ((ac0.in = mlreply("Directory: ", tline, NLINE)) != TRUE)
  1357.         return(ac0.in);
  1358.     
  1359.     ac0.in = chdir(tline);    /* change the current working directory */
  1360.  
  1361.     /*
  1362.     tell the story... success or failure
  1363.     */
  1364.     if (ac0.in) {
  1365.         mlwrite("Error- directory not changed.");
  1366.         return(ac0.in);
  1367.     }
  1368.     else {
  1369.         mlwrite("Directory changed.");
  1370.     return(TRUE);
  1371.     }
  1372. #endif
  1373. }
  1374.  
  1375.  
  1376. #if ORMDNI
  1377.  
  1378. /*
  1379.     superuser on/off toggle routines to override those annoying ACLs
  1380.  
  1381.     usage:  superuser_on();  or  superuser_off();
  1382.  
  1383. */
  1384. int superuser_on()
  1385.  
  1386. {
  1387.     int err;
  1388.  
  1389.     if  (restflag)
  1390.         return(resterr());
  1391.  
  1392.     ac0.lng = -1L;
  1393.     ac1.ulng = 0L;
  1394.     ac2.ulng = 0L;
  1395.     err = 0;
  1396.  
  1397.     if  ((err = sys($SUSER, &ac0, &ac1, &ac2)))
  1398.         if  (err = ERPRV)
  1399.         mlwrite("Error: you are not allowed use of superuser.");
  1400.         else
  1401.         mlwrite("Error turning superuser ON.");
  1402.  
  1403.     return(err);
  1404. }
  1405.  
  1406.  
  1407. int superuser_off()
  1408.  
  1409. {
  1410.     int err;
  1411.  
  1412.     if  (restflag)
  1413.         return(resterr());
  1414.  
  1415.     ac0.ulng = 1L;
  1416.     ac1.ulng = 0L;
  1417.     ac2.ulng = 0L;
  1418.     err = 0;
  1419.  
  1420.     if  ((err = sys($SUSER, &ac0, &ac1, &ac2)))
  1421.         mlwrite("Error turning superuser OFF.");
  1422.  
  1423.     return(err);
  1424. }
  1425. #endif
  1426.  
  1427. #if     ISADIR
  1428. int isadirectory(fstream)
  1429.  
  1430. FILE *fstream;
  1431.  
  1432. {
  1433.     return(isadir(fstream->_file));
  1434. }
  1435. #endif
  1436.  
  1437.  
  1438. /****************************************************************************/
  1439. /*                                                                          */
  1440. /*                                                                          */
  1441. /*  All aosvs$ library routines Copyright (c) 1989 by Douglas C. Rady       */
  1442. /*                                                                          */
  1443. /*                                                                          */
  1444. /****************************************************************************/
  1445.  
  1446. /*
  1447.     aosvs$bsd_dir.h -- a replacement inlcude file under AOS/VS for:
  1448.     <dir.h> -- definitions for 4.2BSD-compatible directory access
  1449.  
  1450.         Taken from GNU's emacs/etc/ndir.h for porting GNU stuff to AOS/VS.
  1451.  
  1452.         All of the usual fields are defined but dd_buf is defined as a char*
  1453.     so we can pass a poniter to a template under AOS/VS.
  1454. */
  1455.  
  1456. #ifndef DIRSIZ
  1457. struct direct {                /* data from readdir() */
  1458.     long        d_ino;        /* inode number of entry */
  1459.     unsigned short    d_reclen;    /* length of this record */
  1460.     unsigned short    d_namlen;    /* length of string in d_name */
  1461.     char        d_name[$MXFN];    /* name of file */
  1462.     };
  1463. #endif
  1464.  
  1465. typedef struct {
  1466.     int    dd_fd;            /* file desc. - channel# under aos/vs */
  1467.     int    dd_loc;            /* offset in block */
  1468.     int    dd_size;        /* amount of valid data */
  1469.         char   *dd_buf;                 /* pointer to wildcard/template */
  1470.     }    DIR;                    /* stream data from opendir() */
  1471.  
  1472. /*
  1473.     set up the MV/Eclipse accumulators used by the  aosvs$  routines
  1474. */
  1475. $align(1) $low32k union aosvs$accumulator { /* dearly beloved, we are gathered here...*/
  1476.     unsigned long * ptr;            /* pointer to unsigned long */
  1477.     char *          cptr;           /* pointer to char */
  1478.     unsigned int  * pint;           /* pointer to unsigned int */
  1479.     unsigned short *psht;           /* pointer to short */
  1480.     unsigned long   ulng;           /* unsigned long */
  1481.     signed long     lng;            /* signed long */
  1482.     unsigned int    uin;            /* unsigned int */
  1483.     signed int      in;             /* signed int */
  1484.     unsigned short usht;            /* unsigned short */
  1485.     unsigned char   chr;            /* a char, unsigned of course!!! */
  1486. } aosvs$ac0, aosvs$ac1, aosvs$ac2;  /* our bountiful accumulators, sigh... */
  1487.  
  1488.  
  1489. /*
  1490.     aosvs$bsd_dir.c -- fake 4.2BSD directory access routines for AOS/VS
  1491.  
  1492.     System call city...
  1493.  
  1494. */
  1495.  
  1496. P_GNFN aosvs$bsd_gnfn_pkt;
  1497.  
  1498. /*
  1499.     aosvs$bsd_closedir
  1500. */
  1501. void closedir(dir_stream)  /* $name("aosvs$bsd_closedir") */
  1502.  
  1503. DIR *dir_stream;
  1504.  
  1505. {
  1506.     aosvs$ac0.ulng = 0L;
  1507.     aosvs$ac2.ulng = 0L;
  1508.     aosvs$ac1.in = dir_stream->dd_fd;   /* load channel number */
  1509.     sys($GCLOSE, &aosvs$ac0, &aosvs$ac1, &aosvs$ac2);
  1510. }
  1511.  
  1512.  
  1513. /*
  1514.     aosvs$bsd_opendir
  1515. */
  1516.  
  1517. DIR *opendir(dir_name) /* name$("aosvs$bsd_opendir") */
  1518.  
  1519. char *dir_name;
  1520.  
  1521. {
  1522.  
  1523. #include    "packets/block_io.h"
  1524.     
  1525.     P_GOPEN gopen_pkt;
  1526.     DIR *dir_stream;
  1527.     int err;
  1528.     char t_name[$MXPL];
  1529.  
  1530.     err = 0;
  1531.     dir_stream = (DIR *) malloc(sizeof(DIR));
  1532.     zero((char *) dir_stream, sizeof(DIR));
  1533.     zero((char *) &aosvs$bsd_gnfn_pkt, sizeof(aosvs$bsd_gnfn_pkt));
  1534.     zero((char *) &gopen_pkt, sizeof(gopen_pkt));
  1535.  
  1536.     err = aosvs$expand_pathname(dir_name, t_name);
  1537.     aosvs$ac0.cptr = t_name;
  1538.     aosvs$ac1.lng = -1L;
  1539.     aosvs$ac2.ptr = &gopen_pkt;
  1540.  
  1541.     /* Try to ?GOPEN the file. */
  1542.     if (err = sys($GOPEN, &aosvs$ac0, &aosvs$ac1, &aosvs$ac2)) {
  1543.         free(dir_stream);       /* Error Will Robinson! Error! Error! */
  1544.         return(NULL);
  1545.     }
  1546.  
  1547.     /* Make sure it is some type of directory! */
  1548.     if ((gopen_pkt.opty_type != $FDIR) && (gopen_pkt.opty_type != $FLDU)
  1549.     && (gopen_pkt.opty_type != $FCPD)) {    /* AOS/VS 7.62 directory types. */
  1550.         dir_stream->dd_fd = (int)gopen_pkt.opch;
  1551.         closedir(dir_stream);
  1552.         free(dir_stream);       /* Error Will Robinson! Error! Error! */
  1553.         return(NULL);
  1554.     }
  1555.  
  1556.     dir_stream->dd_fd = (int)gopen_pkt.opch;    /* stash the channel number */
  1557.     return(dir_stream);
  1558. }
  1559.  
  1560.  
  1561. /*
  1562.     aosvs$bsd_readdir
  1563. */
  1564.  
  1565. struct direct *readdir(dir_stream)   /* name$("aosvs$bsd_readdir") */
  1566.  
  1567. DIR *dir_stream;
  1568.  
  1569. {
  1570.     struct direct *dptr;
  1571.  
  1572.     dptr = NULL;
  1573.     aosvs$ac0.in = 0;
  1574.     aosvs$ac1.in = dir_stream->dd_fd;   /* load channel number */
  1575.  
  1576.     dptr = (struct direct *) malloc(sizeof(struct direct));
  1577.     zero((char *)dptr, sizeof(struct direct));
  1578.  
  1579.     if (dir_stream->dd_loc)
  1580.         aosvs$bsd_gnfn_pkt.nfky     = (short)dir_stream->dd_loc;
  1581.     else
  1582.         aosvs$bsd_gnfn_pkt.nfky     = 0;
  1583.  
  1584.     if (dir_stream->dd_buf)         /* if passed a template */
  1585.         aosvs$bsd_gnfn_pkt.nftp = dir_stream->dd_buf;   /* load it into packet */
  1586.     else
  1587.         aosvs$bsd_gnfn_pkt.nftp   = (char *) -1L;   /* load default flag */
  1588.  
  1589.     aosvs$bsd_gnfn_pkt.nfnm   = dptr->d_name;       /* load buffer ptr */
  1590.     aosvs$ac2.ptr  = &aosvs$bsd_gnfn_pkt;
  1591.     if  (sys($GNFN, &aosvs$ac0, &aosvs$ac1, &aosvs$ac2) == 0)
  1592.     {
  1593.         /* save the AOS/VS internal pointer */
  1594.         dir_stream->dd_loc = (int) aosvs$bsd_gnfn_pkt.nfky;
  1595.  
  1596.         /* load the direct struct values */
  1597.         dptr->d_ino = (long) aosvs$bsd_gnfn_pkt.nfky;   /* fake an inode */
  1598.         dptr->d_reclen = sizeof(struct direct);         /* why? why not? */
  1599.     dptr->d_namlen = strlen(dptr->d_name);          /* handy to have */
  1600.     return(dptr);
  1601.     }
  1602.  
  1603.     free(dptr);
  1604.     return(NULL);    
  1605. }
  1606.  
  1607.  
  1608. /*
  1609.     aosvs$bsd_seekdir
  1610. */
  1611.  
  1612. void seekdir(dir_stream, pos)  /* name$("aosvs$bsd_seekdir") */
  1613.  
  1614. DIR *dir_stream;
  1615. long pos;
  1616.  
  1617. {
  1618.     dir_stream->dd_loc = (short)pos;
  1619. }
  1620.  
  1621.  
  1622. /*
  1623.     aosvs$bsd_telldir
  1624. */
  1625.  
  1626. long telldir(dir_stream)  /* name$("aosvs$bsd_telldir") */
  1627.  
  1628. DIR *dir_stream;
  1629.  
  1630. {
  1631.     return(dir_stream->dd_loc);
  1632. }
  1633.  
  1634.  
  1635. /*
  1636. aosvs$unix_to_aosvs_path.c -- convert a Unix(tm) pathname to a Aos/Vs pathname
  1637.                               We also accept the Ms-Dos '\' seperator and
  1638.                   convert it to the Unix(tm) '/' seperator.  We do
  1639.                   not deal with Ms-Dos device specifiers. The '\'
  1640.                   is handled since most current Ms-Dos C compilers
  1641.                   can deal with either '\' or '/'.
  1642.  
  1643. usage:
  1644.     aosvs$unix_to_aosvs(u_path, a_path);
  1645.  
  1646. where:
  1647. data item name          data type           description
  1648. ----------------------- ------------------  -----------------------------------
  1649. u_path                  char *              char * of Unix(tm) pathname,
  1650.                                             end with null.
  1651. a_path                  char *              char * for Aos/Vs pathname, MUST be
  1652.                                             $MXPL in length.
  1653.  
  1654. -------------------------------------------------------------------------------
  1655. edit history
  1656.  
  1657. who  mm/dd/yy  rev #  what.....................................................
  1658. ---  --------  -----  ---------------------------------------------------------
  1659. dcr  01/27/89  01.00  birth, new life, creation...
  1660. dcr  03/02/89  01.01  cleaned up, added internal temp. storage for path.
  1661. dcr  03/02/89  01.02  added code to deal with Ms-Dog '\' seperator.
  1662. dcr  03/02/89  01.03  added code to skip out if first char is legal Aos/Vs char.
  1663.                       This makes us "just like" _toaos_fid().
  1664. */
  1665. void aosvs$unix_to_aosvs_path(u_path, a_path)
  1666.  
  1667. char *u_path, *a_path;
  1668. {
  1669.  
  1670.     extern int _toaos_fid();        /* Data General library routine */
  1671.  
  1672.     /*
  1673.     local variables
  1674.     */
  1675.     register char *up, *ap;
  1676.     register int dec1;
  1677.     char t_path[$MXPL], octal[4];
  1678.  
  1679.     /*
  1680.     check for null ptrs... no tricks here please...
  1681.     */
  1682.     if ((u_path == NULL) || (a_path == NULL))
  1683.         return;
  1684.  
  1685.     /*
  1686.     copy to register vars.
  1687.     */
  1688.     up = u_path;            /* load ptr to Unix(tm) path */
  1689.     ap = t_path;            /* load ptr to temp. storage area */
  1690.     zero(t_path, $MXPL);    /* zero the temp. storage area */
  1691.             
  1692.     /*
  1693.     to be "just like" DG's _toaos_fid()  we skip out if the first char. is a
  1694.     legal Aos/Vs seperator.  This is from page 2-1 of the "Using Specialized
  1695.     C Functions" manual, DG part number 093-000585-00.
  1696.     */
  1697.     if ((*up == '^') || (*up == '@') || (*up == '=') || (*up == ':')) {
  1698.         strcpy(a_path, u_path);
  1699.     return;
  1700.     }
  1701.  
  1702.     /*
  1703.     step through the unix(tm) pathname and copy or translate bytes into
  1704.     the temp. storage area.
  1705.     */
  1706.     while (*up) {     /* better be NULL terminated!!! */
  1707.         if ((*up == '$') || (*up == '?') || (*up == '\\') || (*up == '_')
  1708.     || ((*up >= '.') && (*up <= ':'))   /* thank you ASCII */
  1709.     || ((*up >= 'A') && (*up <= 'Z'))
  1710.     || ((*up >= 'a') && (*up <= 'z'))) {
  1711.             if (*up == '\\') {   /* convert ms-dos '\' to unix(tm) '/' */
  1712.             *ap++ = '/';
  1713.         up++;
  1714.                 continue;
  1715.             }
  1716.         *ap++ = *up++;
  1717.             continue;
  1718.         }
  1719.  
  1720.         dec1 = 0;
  1721.         zero(octal, 4);
  1722.         *ap++ = '?';            /* marker for octal replacement */
  1723.         dec1 = (int)*up;
  1724.         otoa(dec1, octal);
  1725.         if (dec1 < 64)
  1726.         *ap++ = '0';
  1727.         strcat(ap, octal);
  1728.         if (dec1 >= 64)
  1729.         ap++;
  1730.         ap++;
  1731.     ap++;
  1732.         up++;
  1733.     }
  1734.  
  1735.     *ap = NULL;
  1736.  
  1737.     /*
  1738.     go home...
  1739.     */
  1740.     _toaos_fid(t_path, a_path);
  1741.  
  1742.     return;
  1743. }
  1744.  
  1745. /*
  1746. aosvs$expand_pathname.c
  1747.  
  1748. usage:
  1749.     err = aosvs$expand_pathname(c_path, x_path);
  1750.  
  1751. where:
  1752. data item name          data type           description
  1753. ----------------------- ------------------  -----------------------------------
  1754. err                     int                 Error return, if any.
  1755. c_path                  char *              Current pathname.
  1756. x_path                  char *              Expanded pathname returned here.
  1757.                                             This must be at least $MXPL bytes.
  1758.  
  1759. -------------------------------------------------------------------------------
  1760. edit history
  1761.  
  1762. who  mm/dd/yy  rev #  what.....................................................
  1763. ---  --------  -----  ---------------------------------------------------------
  1764. dcr  03/02/89  01.00  birth, new life, creation...
  1765.  
  1766. */
  1767.  
  1768. /*
  1769. aosvs$expand_pathname.c
  1770.  
  1771. usage:
  1772.     err = aosvs$expand_pathname(c_path, x_path);
  1773.  
  1774. where:
  1775. data item name          data type           description
  1776. ----------------------- ------------------  -----------------------------------
  1777. err                     int                 Error return, if any.
  1778. c_path                  char *              Current pathname.
  1779. x_path                  char *              Expanded pathname returned here.
  1780.                                             This must be at least $MXPL bytes.
  1781.  
  1782. -------------------------------------------------------------------------------
  1783. edit history
  1784.  
  1785. who  mm/dd/yy  rev #  what.....................................................
  1786. ---  --------  -----  ---------------------------------------------------------
  1787. dcr  03/02/89  01.00  birth, new life, creation...
  1788.  
  1789. */
  1790.  
  1791. int aosvs$expand_pathname(c_path, x_path)
  1792.  
  1793. char *c_path, *x_path;
  1794.  
  1795. {
  1796.     /*
  1797.     local variables
  1798.     */
  1799.     char t_path[$MXPL];
  1800.  
  1801.     /*
  1802.     things to do...
  1803.     */
  1804.     zero(t_path, $MXPL);
  1805.     aosvs$unix_to_aosvs_path(c_path, t_path);
  1806.  
  1807.     aosvs$ac2.in = $MXPL;
  1808.     aosvs$ac0.cptr = t_path;
  1809.     aosvs$ac1.cptr = x_path;
  1810.     if (sys($GRNAME, &aosvs$ac0, &aosvs$ac1, &aosvs$ac2))
  1811.         if ((aosvs$ac0.in == ERFDE) || (aosvs$ac0.in == ERFDE))
  1812.             strcpy(x_path, t_path);
  1813.         else
  1814.         return(1);
  1815.  
  1816.     return(0);
  1817. }
  1818.  
  1819. extern DIR        *opendir();
  1820. extern struct direct    *readdir();
  1821. extern long        telldir();
  1822. extern void        seekdir();
  1823. extern void        closedir();
  1824.  
  1825. #define rewinddir( dirp )    seekdir( dirp, 0L )
  1826.  
  1827. #if    COMPLET
  1828.  
  1829.  
  1830. /*    FILE Directory routines        */
  1831.  
  1832. char gnfntmp[NFILEN];   /* wildcard template */
  1833. char gnfnpath[NFILEN];    /* path of file to find */
  1834. char gnfnrbuf[NFILEN];    /* return file buffer */
  1835. DIR *gnfndir;
  1836. struct direct *gnfndirect;
  1837.  
  1838. char PASCAL NEAR *getnfile();
  1839.  
  1840. /*  do a template directory search (for file name completion) */
  1841.  
  1842. char *PASCAL NEAR getffile(fspec)
  1843.  
  1844. char *fspec;    /* pattern to match */
  1845.  
  1846. {
  1847.     register int index;        /* index into various strings */
  1848.  
  1849.         /* clean up from our last time in here... */
  1850.         if (gnfndir) {
  1851.         closedir(gnfndir);
  1852.         free(gnfndir);
  1853.         }
  1854.  
  1855.         if (gnfndirect)
  1856.             free(gnfndirect);
  1857.  
  1858.         /* init. some things... */
  1859.         zero(gnfnpath, NFILEN);
  1860.         zero(gnfnrbuf, NFILEN);
  1861.     zero(gnfntmp, NFILEN);
  1862.         gnfndir = NULL;
  1863.         gnfndirect = NULL;
  1864.  
  1865.         /* first parse the file path off the file spec */
  1866.     strcpy(gnfnpath, fspec);
  1867.     index = strlen(gnfnpath) - 1;
  1868.     while (index >= 0 && (gnfnpath[index] != '/' &&
  1869.                 gnfnpath[index] != '\\' && gnfnpath[index] != ':'))
  1870.         --index;
  1871.  
  1872.     gnfnpath[index+1] = 0;
  1873.  
  1874.         if  ((gnfndir = opendir(gnfnpath)) == NULL)
  1875.         return(NULL);
  1876.  
  1877.         /* build the wildcard or template to use in the lookup */
  1878.         strcpy(gnfntmp, &fspec[index+1]);
  1879.         strcat(gnfntmp, "+");
  1880.         gnfndir->dd_buf = gnfntmp;
  1881.  
  1882.         return(getnfile());
  1883. }
  1884.  
  1885. char *PASCAL NEAR getnfile()
  1886.  
  1887. {
  1888.     register int index;        /* index into various strings */
  1889.  
  1890.         zero(gnfnrbuf, NFILEN);         /* init return buffer */
  1891.  
  1892.     /* and call for the next file */
  1893.         if ((gnfndirect = readdir(gnfndir)) == NULL) {
  1894.         closedir(gnfndir);
  1895.             free(gnfndir);
  1896.             gnfndir = NULL;
  1897.             return(NULL);
  1898.         }
  1899.  
  1900.     /* return the next file name! */
  1901.     strcpy(gnfnrbuf, gnfnpath);
  1902.         strcat(gnfnrbuf, gnfndirect->d_name);
  1903.     mklower(gnfnrbuf);
  1904.         free(gnfndirect);
  1905.         gnfndirect = NULL;
  1906.     return(gnfnrbuf);
  1907. }
  1908. #else
  1909. char *PASCAL NEAR getffile(fspec)
  1910.  
  1911. char *fspec;    /* file to match */
  1912.  
  1913. {
  1914.     return(NULL);
  1915. }
  1916.  
  1917. char *PASCAL NEAR getnfile()
  1918.  
  1919. {
  1920.     return(NULL); }
  1921. #endif
  1922.  
  1923. FILE *xxfopen(fn, mode)     /* expand a pathname and open it */
  1924.  
  1925. char *fn, *mode;
  1926.  
  1927. {
  1928.     char tmppath[NFILEN];               /* temp. to hold expanded pathname */
  1929.  
  1930.     strcpy(tmppath, fn);                        /* load passed pathname */
  1931.     resolve_full_pathname(tmppath, tmppath);    /* expand it... */
  1932.     return(fopen(tmppath, mode));           /* try to open expanded pathname */
  1933. }
  1934.  
  1935. #endif  /* AOSVS */
  1936.